/*=============================================================================
| UART Driver with BUS wrapper
|
| Attention: To keep it simple (and stable), it's ONLY a interrupt version.
|
| Jinfeng Zhuang, 2024.Week16
|
| Verified on LS302
 *===========================================================================*/

#include "bus.h"
#include "ringbuf.h"
#include "swip_uart.h"

// Return the bytes put to ringbuf
static U32 send_int(RAM_t* ram, U8* buf, U32 len)
{
    U32 ret;

    ret = ringbuf_put(&ring_tx, buf, len);

    uart_enable_int_tx();

    return ret;
}

static void single_char_access(RAM_t* ram, U32 dir)
{
    U8 c;

    if (DIR_RD == dir)
    {
        recv_int();
    }
    else
    {
        send_int();
    }
}

static U32 uart_recv(struct swip_uart* uart, U8* buf)
{
    U32 ret;

    switch (uart->mode)
    {
    case UART_MODE_INTERRUPT:
        ret = ringbuf_get(&uart->ring_rx, buf, uart->rx_size);
        if (ret < uart->rx_size)
        {
            uart_enable_int_rx();
        }
        break;
    default:
        return 0;
    }
}

//_____________________________________________________________________________
// Wrapper of SWIP
// Each command => API, Refer to STM32 HAL
//

void swip_uart_event_handler(struct swip_uart* inst, U32 cmd, U32 value, U32 valueL)
{
	U32 i;
	U32 ret;
	
    switch (cmd)
    {
    case SWIP_CMD_INIT:
		inst->ring_tx.buf  = inst->txbuf;
		inst->ring_tx.size = CONFIG_TX_BUF_SIZE;
		
		inst->ring_rx.buf  = inst->rxbuf;
		inst->ring_rx.size = CONFIG_RX_BUF_SIZE;

		hal_uart_baudrate_set(115200);
		hal_uart_enable(1);
        break;
    case UART_CMD_SEND:
        if (UART_MODE_BLOCK == inst->mode)
        {
			for (i = 0; i < inst->tx_remain; i++)
			{
            	uart_send_char(((U8*)value)[i]);
			}

			inst->tx_remain = 0;
        }
        else if (UART_MODE_INTERRUPT == inst->mode)
        {
			ret = ringbuf_put(inst->ring_tx, (U8*)value, valueL);
            uart_enable_int_tx();
        }
        break;
	case UART_CMD_RECV:
        ret = ringbuf_get(uart->rxbuf, uart->size);
        if (ret < uart->size)
        {
            uart->rx_size += (uart->size - ret);
            uart_enable_int_rx();
        }
		break;
    case UART_RX_BUF:
        ringbuf_put(uart->rxbuf, value);

        if (0xFFFFFFFF != uart->rx_size)
        {
            uart->rx_size--;
            if (0 == uart->rx_size)
            {
                uart_disable_int_rx();
            }
        }
        break;
    }
}
